#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <atomic>
#include <stdio.h>
#include <fstream>
#include <memory>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h> 
#include <jsoncpp/json/json.h>
#include <boost/algorithm/string.hpp>
namespace ns_util
{
    class Time_Util
    {
    public:
        // struct timeval
        // {
        //     time_t tv_sec;       /* Seconds */   秒
        //     suseconds_t tv_usec; /* Microseconds */   微秒
        // };
        // 获取时间戳
        static std::string GetTimeStamp()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec);
        }
        // 获取毫秒级时间戳
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000); // 毫秒=秒*1000+微秒/1000
        }
    };
    const std::string path = "./temp/";
    class Path_Util
    {
    private:
        static std::string AddSuffix(const std::string &file_name, const std::string &Suffix)
        {
            std::string file_path;
            file_path += path;
            file_path += file_name;
            file_path += Suffix;
            return file_path;
        }

    public:
        // 编译阶段所需要的文件路径
        static std::string Src(const std::string &file_name)
        {
            return AddSuffix(file_name, ".cpp");
        }
        static std::string Exe(const std::string &file_name)
        {
            return AddSuffix(file_name, ".exe");
        }
        static std::string CompileError(const std::string &file_name)
        {
            return AddSuffix(file_name, ".compile_error");
        }
        // 运行阶段所需要的文件路径
        static std::string Stdin(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stdin");
        }
        static std::string Stdout(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stdout");
        }
        // 运行报错的文件路径
        static std::string Stderr(const std::string &file_name)
        {
            return AddSuffix(file_name, ".stderr");
        }
    };
    class File_Util
    {
    public:
        static bool Is_File_Exist(const std::string &file_name)
        {
            struct stat st;
            int ret = stat(file_name.c_str(), &st);
            if (ret == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        // 获取唯一的文件名,避免多用户之间文件冲突
        static std::string Unique_File_Name()
        {
            // 采用毫秒级时间戳+唯一性的id作为文件名
            static std::atomic_uint id(0);
            id++;
            std::string ms = Time_Util::GetTimeMs();
            std::string unique_file_name = ms + "_" + std::to_string(id);
            return unique_file_name;
        }
        //将content中的内容写到file_name文件中
        static bool Write_File(const std::string file_name,const std::string& content)
        {
            std::ofstream out(file_name);
            if(!out.is_open())
            {
                return false;
            }
            out.write(content.c_str(),content.size());
            out.close();
            return true;
        }
        //将file_name文件中的内容读取到content中,keep决定是否保留\n
        static bool Read_File(const std::string file_name, std::string& content, bool keep = false)
        {
            content.clear();
            std::ifstream in(file_name);
            while(!in.is_open())
            {
                return false;
            }
            std::string line;
            while(getline(in,line))
            {
                content+=line;
                //getline不保存行分割符,但是有时我们需要保留行分隔符,就可以使用keep作为是否保留行分隔符的标识
                //一行读完如果keep为true说明需要保存行分割符就加上
                content+=(keep?"\n":"");
            }
            in.close();
            return true;
        }
    };
    class String_Util
    {
    public:
        static void SplitString(const std::string &str, std::vector<std::string> *target, const std::string &sep)
        {
            boost::split((*target), str, boost::is_any_of(sep), boost::algorithm::token_compress_on);
            // 将str分割结果保存在target中,只要碰到sep中的任何一个字符都进行分割,并且进行结果压缩
        }
    };
    class Json_Util{
        public:
        static bool Serialization(const Json::Value& root,std::string& str)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            std::stringstream ss;
            int ret=sw->write(root,&ss);
            if(ret!=0)
            {
                return false;
            }
            str=ss.str();
            return true;
        }
        static bool Deserialization(Json::Value& root,const std::string& str)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret=cr->parse(str.c_str(),str.c_str()+str.size(),&root,nullptr);
            if(ret==false){
                return false;
            }
            return true;
        }
    };
}